Skip to content

Fix: Use consistent cursor height instead of per-character metrics#1182

Open
JimTyrrell wants to merge 5 commits into
AppFlowy-IO:mainfrom
JimTyrrell:fix/consistent-cursor-height
Open

Fix: Use consistent cursor height instead of per-character metrics#1182
JimTyrrell wants to merge 5 commits into
AppFlowy-IO:mainfrom
JimTyrrell:fix/consistent-cursor-height

Conversation

@JimTyrrell

Copy link
Copy Markdown

Summary

  • Fixes cursor height inconsistency where the cursor appears shorter after spaces compared to letters
  • Most noticeable on iOS but affects all platforms

Problem

The cursor height was calculated using getFullHeightForCaret() which returns different heights depending on the character at the cursor position. Spaces have different text metrics than letters, causing the cursor to "jump" or change height as you type.

Solution

Replace the dynamic getFullHeightForCaret() call with a consistent formula based on font size:

final fontSize = textStyleConfiguration.text.fontSize ?? 16.0;
double? cursorHeight = fontSize * 1.2;

This ensures the cursor height remains stable regardless of the character at the cursor position.

Related Issues

Fixes #1137
Related to #1136, #624

Test Plan

  1. Open editor on iOS (or any platform)
  2. Type text with spaces: "hello world"
  3. Move cursor between letters and spaces
  4. Observe cursor height remains consistent

@CLAassistant

CLAassistant commented Feb 2, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ JimTyrrell
❌ Jim Tyrrell


Jim Tyrrell seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

The cursor height was calculated using getFullHeightForCaret() which
returns different heights depending on the character at the cursor
position. This caused the cursor to appear shorter when positioned
after spaces compared to letters, especially noticeable on iOS.

This fix uses a consistent formula (fontSize * 1.2) to ensure the
cursor height remains stable regardless of the character at the
cursor position.

Fixes AppFlowy-IO#1137
@JimTyrrell JimTyrrell force-pushed the fix/consistent-cursor-height branch from 7ae10e1 to bc7fbe1 Compare February 2, 2026 17:46
Jim Tyrrell and others added 4 commits June 24, 2026 16:01
AppFlowyClipboard was a plain-text-only stub: setData dropped the `html`
argument and getData hard-coded `html: null`. With no html on the clipboard,
the editor's paste handler skipped its formatting-preserving `pasteHtml`
branch and fell back to a bare plain-text delta — so copy→paste of formatted
text (bold/italic/lists/headings) lost ALL formatting, even within the same
app.

Retain the last copied html in-process and return it on getData only when the
system clipboard still holds the matching text we wrote (same-app copy→paste
round trip); otherwise return html:null so external plain-text paste degrades
gracefully. The system clipboard still receives text/plain as before, so
cross-app plain paste is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The HTML encoder appended a list item's child list nodes (bare <li>) directly
inside the parent <li> with no enclosing <ol>/<ul>. The emitted markup
(<li>parent<li>child</li></li>) is "fixed" by every HTML parser by flattening
the inner <li> into a sibling — so a nested list item lost its indent level
and was renumbered to top level on copy/paste.

Add processChildrenNodesPreservingListNesting (wraps consecutive same-type
list children in their own <ol>/<ul>; non-list children pass through) and use
it from the numbered + bulleted list parsers. Only affects lists WITH children
(nested), so flat lists are unchanged. Checkbox/todo nesting is unchanged
(separate follow-up).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The encoder emits a to-do item as <div><input type="checkbox" [checked]/>text
</div>, but the decoder had no handler: <div> fell through to the default
(plain paragraph) and the <input> was ignored — so pasting a checklist lost
both the todo_list block type and the checked state.

Add _parseDivElement: when a <div> contains a checkbox <input>, build a
todo_list node carrying the checked state and the remaining inline content;
otherwise fall back to paragraph parsing (non-todo divs unaffected).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] cursorHeight

2 participants